home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / sipp / libsipp / torus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-03  |  5.1 KB  |  201 lines

  1. /**
  2.  ** sipp - SImple Polygon Processor
  3.  **
  4.  **  A general 3d graphic package
  5.  **
  6.  **  Copyright Equivalent Software HB  1992
  7.  **
  8.  ** This program is free software; you can redistribute it and/or modify
  9.  ** it under the terms of the GNU General Public License as published by
  10.  ** the Free Software Foundation; either version 1, or any later version.
  11.  ** This program is distributed in the hope that it will be useful,
  12.  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  ** GNU General Public License for more details.
  15.  ** You can receive a copy of the GNU General Public License from the
  16.  ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  **/
  18.  
  19. /**
  20.  ** torus.c - Creating a torus as a sipp object.
  21.  **/
  22.  
  23. #include <xalloca.h>
  24. #include <math.h>
  25.  
  26. #include <sipp.h>
  27. #include <primitives.h>
  28.  
  29.  
  30. #define SWAPARR(a, b) {Vector *tmp; tmp = a; a = b; b = tmp;}
  31.  
  32.  
  33. static Vector *arr1;
  34. static Vector *arr2;
  35. static Vector *tx1;
  36. static Vector *tx2;
  37.  
  38.  
  39. static void
  40. arr_rot(len, angle, texture)
  41.     int    len;
  42.     double angle;
  43.     int    texture;
  44. {
  45.     int    i;
  46.     double sa, ca;
  47.  
  48.     sa = sin(angle);
  49.     ca = cos(angle);
  50.     for (i = 0; i < len; i++) {
  51.         arr2[i].x = arr1[i].x * ca - arr1[i].y * sa;
  52.         arr2[i].y = arr1[i].x * sa + arr1[i].y * ca;
  53.         arr2[i].z = arr1[i].z;
  54.         switch (texture) {
  55.           case NATURAL:
  56.           case CYLINDRICAL:
  57.           case SPHERICAL:
  58.             tx2[i].x = tx1[i].x + angle / (2.0 * M_PI);
  59.             tx2[i].y = tx1[i].y;
  60.             tx2[i].z = tx1[i].z;
  61.             break;
  62.  
  63.           case WORLD:
  64.           default:
  65.             tx2[i] = arr2[i];
  66.             break;
  67.         }
  68.     }
  69.     switch (texture) {
  70.       case NATURAL:
  71.       case CYLINDRICAL:
  72.       case SPHERICAL:
  73.         tx2[i].x = tx1[i].x + angle / (2.0 * M_PI);
  74.         tx2[i].y = tx1[i].y;
  75.         tx2[i].z = tx1[i].z;
  76.         break;
  77.  
  78.       case WORLD:
  79.       default:
  80.         tx2[i] = tx2[0];
  81.         break;
  82.     }
  83. }
  84.  
  85.  
  86. static void
  87. push_band(len)
  88.     int    len;
  89. {
  90.     int i, j;
  91.  
  92.     for (i = 0; i < len; i++) {
  93.         j = (i + 1) % len;
  94.         vertex_tx_push(arr1[i].x, arr1[i].y, arr1[i].z, 
  95.                        tx1[i].x, tx1[i].y, tx1[i].z);
  96.         vertex_tx_push(arr2[i].x, arr2[i].y, arr2[i].z, 
  97.                        tx2[i].x, tx2[i].y, tx2[i].z);
  98.         vertex_tx_push(arr2[j].x, arr2[j].y, arr2[j].z, 
  99.                        tx2[i + 1].x, tx2[i + 1].y, tx2[i + 1].z);
  100.         vertex_tx_push(arr1[j].x, arr1[j].y, arr1[j].z, 
  101.                        tx1[i + 1].x, tx1[i + 1].y, tx1[i + 1].z);
  102.         polygon_push();
  103.     }
  104. }
  105.  
  106.  
  107.  
  108. Object *
  109. sipp_torus(bigradius, smallradius, res1, res2, surface, shader, texture)
  110.     double  bigradius;      /* Radius of the ring */
  111.     double  smallradius;    /* Radius of the "tube" */
  112.     int     res1;           /* Number of polygons around the ring */
  113.     int     res2;           /* Number of polygons around the tube */
  114.     void   *surface;
  115.     Shader *shader;
  116.     int     texture;
  117. {
  118.     Object *torus;
  119.     double  angle;
  120.     int     i;
  121.  
  122.     /* Create two arrays to hold vertices around the tube */
  123.     arr1 = (Vector *)alloca(res2 * sizeof(Vector));
  124.     arr2 = (Vector *)alloca(res2 * sizeof(Vector));
  125.  
  126.     /* Create two arrays to hold texture coordinates  around the tube */
  127.     tx1 = (Vector *)alloca((res2 + 1) * sizeof(Vector));
  128.     tx2 = (Vector *)alloca((res2 + 1) * sizeof(Vector));
  129.  
  130.     for (i = 0; i < res2; i++) {
  131.         angle = i * 2.0 * M_PI / res2 - M_PI / 4.0;
  132.         arr1[i].x = bigradius + smallradius * cos(angle);
  133.         arr1[i].y = 0.0;
  134.         arr1[i].z = smallradius * sin(angle);
  135.         switch (texture) {
  136.           case NATURAL:
  137.             tx1[i].x = 0.0;
  138.             tx1[i].y = (double)i / (double)res2;
  139.             tx1[i].z = 0.0;
  140.             break;
  141.  
  142.           case CYLINDRICAL:
  143.             tx1[i].x = 0.0;
  144.             tx1[i].y = (arr1[i].z + smallradius) / (2.0 * smallradius);
  145.             tx1[i].z = 0.0;
  146.             break;
  147.  
  148.           case SPHERICAL:
  149.             tx1[i].x = 0.0;
  150.             tx1[i].y = atan(arr1[i].z / arr1[i].x) / M_PI + 0.5;
  151.             tx1[i].z = 0.0;
  152.             break;
  153.  
  154.           case WORLD:
  155.           default:
  156.             tx1[i] = arr1[i];
  157.             break;
  158.         }
  159.     }
  160.  
  161.     switch (texture) {
  162.       case NATURAL:
  163.         tx1[i].x = 0.0;
  164.         tx1[i].y = (double)i / (double)res2;
  165.         tx1[i].z = 0.0;
  166.         break;
  167.         
  168.       case CYLINDRICAL:
  169.         tx1[i].x = 0.0;
  170.         tx1[i].y = (arr1[0].z + smallradius) / (2.0 * smallradius);
  171.         tx1[i].z = 0.0;
  172.         break;
  173.         
  174.       case SPHERICAL:
  175.         tx1[i].x = 0.0;
  176.         tx1[i].y = atan(arr1[0].z / arr1[0].x) / M_PI + 0.5;
  177.         tx1[i].z = 0.0;
  178.         break;
  179.         
  180.       case WORLD:
  181.       default:
  182.         tx1[i] = tx1[0];
  183.         break;
  184.     }
  185.     
  186.     /* Sweep out the torus by rotating the two perimeters */
  187.     /* defined in arr1 and arr2. */
  188.     for (i = 0; i < res1; i++) {
  189.         arr_rot(res2, 2.0 * M_PI / (double)res1, texture);
  190.         push_band(res2);
  191.         SWAPARR(arr1, arr2)
  192.         SWAPARR(tx1, tx2)
  193.     }
  194.  
  195.     torus = object_create();
  196.     object_add_surface(torus, surface_create(surface, shader));
  197.  
  198.     return torus;
  199. }
  200.  
  201.